package com.luoqiz.project.archiver;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

public class Archiver {

	public static String jieArchiver(String srcPath, String destPath) {
		try {
			FileInputStream fin = new FileInputStream(srcPath);
			while (hasFile(fin)) {
				fenxie(fin, destPath);
			}
			fin.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return "over";
	}

	/**
	 * 判读是否还有文件
	 * 
	 * @param fin
	 * @return
	 */
	private static boolean hasFile(FileInputStream fin) {
		boolean b = false;
		try {
			if (fin.read() != -1) {
				fin.skip(-1);
				b = true;
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return b;
	}

	private static void fenxie(FileInputStream fin, String destPath) {
		FileOutputStream fout = null;
		try {
			byte[] fileNameLenBytes = new byte[4];
			fin.read(fileNameLenBytes);
			int fileNameLen = bytesToInt(fileNameLenBytes);
			System.out.println("文件名长度" + fileNameLen);
			byte[] fileNameBytes = new byte[fileNameLen];
			fin.read(fileNameBytes);
			String fileName = bytesToString(fileNameBytes);
			fout = new FileOutputStream(destPath + "/" + fileName);

			System.out.println("文件名：" + fileName);
			byte[] fileLenBytes = new byte[4];
			fin.read(fileLenBytes);
			int fileLen = bytesToInt(fileLenBytes);
			System.out.println("文件长度" + fileNameLen);
			//复制方式
			//第一种
			byte[] copy = new byte[1024];
			int i = 1;
			while (fileLen - (i * copy.length) >= 0) {
				fin.read(copy);
				fout.write(copy);
				i++;
			}
			int lastLen=0;
			if ((lastLen=fileLen % copy.length) != 0) {
				byte[] lastCopy=new byte[lastLen];
				fin.read(lastCopy);
				fout.write(lastCopy);
				
			}

			// 第二种直接复制
			// byte[] fileContent = new byte[fileLen];
			// fin.read(fileContent);
			// fout.write(fileContent);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				fout.flush();
				fout.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private static int bytesToInt(byte[] fileLengBytes) {
		int i0 = fileLengBytes[3] & 0xff << 24;
		int i1 = fileLengBytes[2] & 0xff << 16 ;
		int i2 = fileLengBytes[1] & 0xff << 8 ;
		int i3 = fileLengBytes[0];
		return i0 | i1 | i2 | i3;
	}

	private static String bytesToString(byte[] fileNameBytes) {
		String string = null;
		try {
			string = new String(fileNameBytes, "utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return string;
	}

	public static String archiver(String destPath, String... srcPaths) {
		FileOutputStream fout = null;
		try {
			fout = new FileOutputStream(new File(destPath));
			for (String srcPath : srcPaths) {
				addFile(fout, srcPath);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return "归档路径出错";
		} finally {
			try {
				fout.flush();
				fout.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		System.out.println("归档完成");
		return "over";
	}

	/**
	 * 添加文件到归档文件中
	 * 
	 * @param fout
	 * @param srcFile
	 */
	private static void addFile(FileOutputStream fout, String srcFile) {
		// 1:文件名称 270个字节存放 windows最大长度为260个字节，linux最大256个字节
		File f = new File(srcFile);
		byte[] fileName = StringToBytes(f.getName());
		System.out.println("文件名------" + f.getName());
		byte[] fileNameLeng = intToByteArray(fileName.length);
		System.out.println(fileName.length);
		// 2:获取文件长度 4个字节存放int
		byte[] fileLeng = new byte[4];
		FileInputStream fin = null;
		try {
			fin = new FileInputStream(f);
			fileLeng = intToByteArray(fin.available());
			System.out.println(srcFile + "--文件长度:" + fin.available());
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 3:写入
		// 固定长度270字节为文件名，随后固定长度4字节为文件长度
		try {
			fout.write(fileNameLeng);
			fout.write(fileName);
			fout.write(fileLeng);
			int len = -1;
			byte[] b = new byte[1024];
			while ((len = fin.read(b)) != -1) {
				fout.write(b, 0, len);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				fin.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 整数转数组
	 * 
	 * @param arg1
	 * @return
	 */
	private static byte[] intToByteArray(int arg1) {
		byte[] b = new byte[4];
		b[0] = (byte) arg1;
		b[1] = (byte) (arg1 >> 8);
		b[2] = (byte) (arg1 >> 16);
		b[3] = (byte) (arg1 >> 24);
		return b;
	}

	/**
	 * 将字符串转为字节数组
	 * 
	 * @param srcFile
	 * @return
	 */
	private static byte[] StringToBytes(String src) {
		try {
			return src.getBytes("UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

}
